package com.southgis.ibase.sql.config;

import com.southgis.ibase.sql.utils.DatabaseUtil;
import com.alibaba.druid.util.JdbcConstants;
import com.southgis.ibase.sql.enums.DataSourceType;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

public class DataSourceDefineTemplateProp
{
	@Setter
	List<DataSourceDefineTemplate> define;
	
	public List<DataSourceDefineTemplate> getDefine()
	{
		if(define==null)
			define=new ArrayList<>();
		return define;
	}
	
	/**
	 * 默认数据源配置
	 */
	@Autowired(required = false)
	@Getter
	@Setter
	DataSourceProperties dsConfig;
	
	@Autowired(required = false)
	DataSource dataSource;
	
	@PostConstruct
	public void init()
	{
		supportDefineTemplate();
		DatabaseUtil.init(dsConfig,this,dataSource);
	}
	
	/**
	 * 获取所有定义模板信息的类型名
	 * @return
	 */
	public List<String> gainDefineTemplateTypes()
	{
		List<String> types=new ArrayList<>();
		for(DataSourceDefineTemplate item:getDefine()) {
			types.add(item.getType());
		}
		return types;
	}

	/**
	 * 获取已存在的指定类型定义模板，如果不存在，返回null
	 * @param type
	 * @return
	 */
	public DataSourceDefineTemplate getExistDefineTemplate(String type)
	{
		for(DataSourceDefineTemplate item:getDefine()) {
			if(item.getType().equalsIgnoreCase(type))
				return item;
		}
		return null;
	}
	
	/**
	 * 获取指定类型的数据源模板信息，如果不存在，返回一个通用信息的对象（这个通用对象不一定满足期望需求）
	 * @param type
	 * @return 不会返回null
	 */
	public DataSourceDefineTemplate gainDefineTemplate(String type)
	{
		DataSourceDefineTemplate temp=getExistDefineTemplate(type);
		return temp==null?addDefaultDataSourceTemplate(type):temp;
	}

	private void supportDefineTemplate()
	{
		String type=DataSourceType.MYSQL;
		DataSourceDefineTemplate temp=getExistDefineTemplate(type);
		if(temp==null) {
			temp=new DataSourceDefineTemplate(type,
					JdbcConstants.MYSQL_DRIVER_6,
					"jdbc:mysql://{host}:{port}/{database}"
						+"?serverTimezone=Asia/Shanghai"
						+"&useUnicode=true"
						+"&characterEncoding=utf-8"
						+"&createDatabaseIfNotExist=true"
						+"&useSSL=false"
						+"&nullCatalogMeansCurrent=true",
					"org.hibernate.dialect.MySQL57Dialect",
					"com.southgis.ibase.sql.func.MysqlFunc");
			getDefine().add(temp);
		}
		
		type=DataSourceType.ORACLE;
		temp=getExistDefineTemplate(type);
		if(temp==null) {
			temp=new DataSourceDefineTemplate(type,
					JdbcConstants.ORACLE_DRIVER2,
					"jdbc:oracle:thin:@//{host}:{port}/{database}",
					"com.southgis.ibase.utils.web.Oracle10gexDialect",
					"com.southgis.ibase.sql.func.OracleFunc");
			getDefine().add(temp);
		}
		
		type=DataSourceType.POSTGRESQL;
		temp=getExistDefineTemplate(type);
		if(temp==null) {
			temp=new DataSourceDefineTemplate(type,
					JdbcConstants.POSTGRESQL_DRIVER,
					"jdbc:postgresql://{host}:{port}/{database}",
					"org.hibernate.dialect.PostgreSQLDialect",
					"com.southgis.ibase.sql.func.PostgresqlFunc");
			getDefine().add(temp);
		}

		
		type=DataSourceType.DM;
		temp=getExistDefineTemplate(type);
		if(temp==null) {
			temp=new DataSourceDefineTemplate(type,
					JdbcConstants.DM_DRIVER,
					"jdbc:dm://{host}:{port}",
					"org.hibernate.dialect.DmDialect",
					"com.southgis.ibase.sql.func.DmFunc");
			getDefine().add(temp);
		}
		
		type=DataSourceType.KINGBASE;
		temp=getExistDefineTemplate(type);
		if(temp==null) {
			temp=new DataSourceDefineTemplate(type,
					"com.kingbase8.Driver",
					"jdbc:kingbase8://{host}:{port}/{database}",
					"org.hibernate.dialect.Kingbase8Dialect",
					"com.southgis.ibase.sql.func.KingbaseFunc");
			getDefine().add(temp);
		}

	}
	private DataSourceDefineTemplate addDefaultDataSourceTemplate(String type)
	{
		type=type.toLowerCase();
		String baseName=StringUtils.capitalize(type);
		
		//检查指定的处理类是否存在
		String funcClass="com.southgis.ibase.sql.func."+baseName+"Func";
		Class<?> clazz=null;
		try {
			clazz=Class.forName(funcClass);
		}catch (Exception e) {
			//不需要
		}
		if(clazz==null) { //通用功能调用方法
			funcClass="com.southgis.ibase.sql.func.CommonFunc";
		}
		
		//检查指定的方言类是否存在
		String dialectClass="org.hibernate.dialect."+baseName+"Dialect";
		clazz=null;
		try {
			clazz=Class.forName(dialectClass);
		}catch (Exception e) {
			//不需要
		}
		if(clazz==null) { //通用方言
			dialectClass="com.southgis.ibase.sql.func.CommonDialect";
		}
		
		DataSourceDefineTemplate defTemp=null;
		defTemp=new DataSourceDefineTemplate(type,
				"", //驱动类为空
				"jdbc:"+type+"://{host}:{port}/{database}", //最常规的url格式
				dialectClass,
				funcClass);
		
		getDefine().add(defTemp);
		
		return defTemp;
	}
	
	/**
	 * 手动添加数据源模板信息（不会验证指定类型的定义是否存在）
	 * @param type 数据源类型（与DataSourceTypeEnum对应），不能为空。
	 * @param driverClass 驱动类名
	 * @param url 连接串格式（如果有参数，也要带参数），其中包含占位符：
	 *   {host} 指服务地址，
	 *   {port} 指服务端口号，
	 *   {database} 指库名（或实例名、服务名，不同数据源定义不一样）。
	 * @param dialect 方言类名，如果传入空，则使用{@link com.southgis.ibase.sql.func.CommonDialect}（但不一定符合当前数据源预期结果）
	 * @param funcClass SQL片段特殊语法处理类名，如果传入空，则使用{@link com.southgis.ibase.sql.func.CommonFunc}（但不一定符合当前数据源预期结果）
	 * @return
	 */
	public DataSourceDefineTemplate addDataSourceTemplate(String type,String driverClass,String url,
			String dialect,String funcClass)
	{
		type=type.toLowerCase();
		DataSourceDefineTemplate defTemp=new DataSourceDefineTemplate(type,
				driverClass,
				url,
				StringUtils.isEmpty(dialect)?"com.southgis.ibase.sql.func.CommonDialect":dialect,
				StringUtils.isEmpty(funcClass)?"com.southgis.ibase.sql.func.CommonFunc":funcClass
		);
		getDefine().add(defTemp);

		return defTemp;
	}
}
